using System;

namespace GeneticAlgorithms.Tools
{
    /// <summary>
    /// Random-number generator for GAs.
    /// </summary>
    public class GeneticRandomGenerator : IGeneticRandomGenerator
    {
        private Random random = new Random();

        /// <summary>
        /// Returns a nonnegative random number.
        /// </summary>
        /// <returns>
        /// A 32-bit signed integer greater than or equal to zero and less than System.Int32.MaxValue.
        /// </returns>
        public int Next()
        {
            return random.Next();
        }

        /// <summary>
        /// Returns a nonnegative random number less than the specified maximum.
        /// </summary>
        /// <param name="maxValue">The exclusive upper bound of the random number to
        /// be generated. maxValue must be greater than or equal to zero.</param>
        /// <returns>
        /// A 32-bit signed integer greater than or equal to zero,
        /// and less than maxValue; that is, the range of return values ordinarily
        /// includes zero but not maxValue. However, if maxValue equals zero, maxValue
        /// is returned.
        /// </returns>
        /// <exception cref="System.ArgumentOutOfRangeException">Thrown when maxValue is less than zero.</exception>
        public int Next(int maxValue)
        {
            return random.Next(maxValue);
        }

        /// <summary>
        /// Returns a random number between 0.0 and 1.0.
        /// </summary>
        /// <returns>
        /// A double-precision floating point number greater than or equal to
        /// 0.0, and less than 1.0.
        /// </returns>
        public double NextDouble()
        {
            return random.NextDouble();
        }

        /// <summary>
        /// Returns a random boolean value, with the given
        /// probability of being <c>true</c>.
        /// </summary>
        /// <param name="probability">The probability the generated boolean will be <c>true</c>.</param>
        /// <returns>A boolean value.</returns>
        public bool NextBool(double probability)
        {
            return random.NextDouble() < probability;
        }

        /// <summary>
        /// Returns a random boolean value, with a 50%
        /// probability of being <c>true</c>.
        /// </summary>
        /// <returns>A boolean value.</returns>
        public bool NextBool()
        {
            return NextBool(.5);
        }

        static IGeneticRandomGenerator defaultInstance = new GeneticRandomGenerator();
        /// <summary>
        /// Gets or sets the default random generator instance.
        /// </summary>
        /// <value>The default random generator instance.</value>
        public static IGeneticRandomGenerator Default
        {
            get { return defaultInstance; }
            set { defaultInstance = value; }
        }
    }
}
